package src;

import pjwstk.jps.ast.Expression;
import pjwstk.jps.ast.binary.CommaExpression;
import pjwstk.jps.ast.binary.DotExpression;
import pjwstk.jps.ast.binary.GreaterThanExpression;
import pjwstk.jps.ast.binary.UnionExpression;
import pjwstk.jps.ast.binary.WhereExpression;
import pjwstk.jps.ast.terminal.IntegerTerminal;
import pjwstk.jps.ast.terminal.NameTerminal;
import pjwstk.jps.datastore.*;
import pjwstk.jps.interpreter.envs.*;
import pjwstk.jps.interpreter.qres.QResStack;
import pjwstk.jps.result.*;

import java.util.*;

/**
 * @author s9111_s10304
 *
 */
public class Main4
{
	@SuppressWarnings("unused")
    public static void main(String[] args) {
		// pr4 - ENVS
        System.out.println("pr4 - ENVS");
        
        // QRES1 + ENVS1: ((emp where married).book.author) union (realNumber)
        System.out.println("QRES1 + ENVS1: ((emp where married).book.author) union (realNumber)");

        // AST1: ((emp where married).book.author) union (realNumber)
        Expression expression1 = new Expression(
            new UnionExpression(
                new DotExpression(
                    new DotExpression(
                        new WhereExpression(
                            new NameTerminal("emp"),
                            new NameTerminal("married")
                        ),
                        new NameTerminal("book")
                    ),
                    new NameTerminal("author")
                ),
                new NameTerminal("realNumber")
            )
        );
        
        ENVS envs1 = new ENVS();           // envs1||
        QResStack qres1 = new QResStack(); // qres1||
        SBAStore store1 = new SBAStore();  // store1||
        
        store1.loadXML(".\\s9111_s10304_pr4\\res\\data.xml");
        envs1.init(store1.getEntryOID(), store1); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25)
        store1.PrintObjects(store1.retrieve(store1.getEntryOID()));
        System.out.println(store1.getString());
        
        
        // WhereExpression
        IBagResult whereRes11 = new BagResult(null);
        ArrayList<ISingleResult> whereResCollection11 = new ArrayList<ISingleResult>();

        IBagResult qRes11 = envs1.bind("emp");
        qres1.push(qRes11); // qres1|| bag(2, 15)
        
        IBagResult qRes12 = (IBagResult)qres1.pop(); // qres1||
        
        // emp(2)
        ArrayList<ISingleResult> collection11 = (ArrayList<ISingleResult>)qRes12.getElements();
        IENVSFrame frame11 = envs1.nested(collection11.get(0), store1);
        envs1.push(frame11); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25) | number(3), fName(4), lName(5), address(6), married(11), book(12)
        
        IBagResult qRes13 = envs1.bind("married");
        qres1.push(qRes13); // qres1|| bag(11)
        
        envs1.pop(); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes14 = (IBagResult)qres1.pop(); // qres1||
        
        ArrayList<ISingleResult> collection12 = (ArrayList<ISingleResult>)qRes14.getElements();
        ISBAObject sbaObj11 = store1.retrieve(((IReferenceResult)collection12.get(0)).getOIDValue());
        
        if (((BooleanObject)sbaObj11).getValue() == true)  // emp(2).married == true
            whereResCollection11.add(collection11.get(0));
        
        // emp(15)
        IENVSFrame frame12 = envs1.nested(collection11.get(1), store1);
        envs1.push(frame12); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25) | number(16), fName(17), lName(18), address(19), married(24)
        
        IBagResult qRes15 = envs1.bind("married");
        qres1.push(qRes15); // qres1|| bag(24)
        
        envs1.pop(); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes16 = (IBagResult)qres1.pop(); // qres1||
        
        ArrayList<ISingleResult> collection13 = (ArrayList<ISingleResult>)qRes16.getElements();
        ISBAObject sbaObj12 = store1.retrieve(((IReferenceResult)collection13.get(0)).getOIDValue());
        
        if (((BooleanObject)sbaObj12).getValue() == true) // emp(15).married == false
            whereResCollection11.add(collection11.get(1));

        whereRes11 = new BagResult(whereResCollection11);
        qres1.push(whereRes11); // qres1|| bag(2)
        
        
        // DotExpression
        IBagResult dotRes11 = new BagResult(null);
        
        IBagResult qRes17 = (IBagResult)qres1.pop(); // qres1||
        
        ArrayList<ISingleResult> collection14 = (ArrayList<ISingleResult>)qRes17.getElements();
        
        IENVSFrame frame13 = envs1.nested(collection14.get(0), store1);
        envs1.push(frame13); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25) | number(3), fName(4), lName(5), address(6), married(11), book(12) 
        
        IBagResult qRes18 = envs1.bind("book");
        qres1.push(qRes18); // qres1|| bag(12)
        
        envs1.pop(); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes19 = (IBagResult)qres1.pop(); // qres1||
        
        dotRes11 = qRes19;
        qres1.push(dotRes11); // qres1|| bag(12)
        
        
        // DotExpression
        IBagResult dotRes12 = new BagResult(null);
        
        IBagResult qRes110 = (IBagResult)qres1.pop(); // qres1||
        
        ArrayList<ISingleResult> collection15 = (ArrayList<ISingleResult>)qRes110.getElements();
        
        IENVSFrame frame14 = envs1.nested(collection15.get(0), store1);
        envs1.push(frame14); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25) | author(13), title(14)
        
        IBagResult qRes111 = envs1.bind("author");
        qres1.push(qRes111); // qres1|| bag(13)
        
        envs1.pop(); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes112 = (IBagResult)qres1.pop(); // qres1||
        
        dotRes12 = qRes112;
        qres1.push(dotRes12); // qres1|| bag(13)
        
        
        // UnionExpression
        IBagResult unionRes11 = new BagResult(null);
        ArrayList<ISingleResult> unionResCollection11 = new ArrayList<ISingleResult>();
        
        IBagResult qRes113 = (IBagResult)qres1.pop(); // qres1||
        
        ArrayList<ISingleResult> collection18 = (ArrayList<ISingleResult>)qRes113.getElements();
        
        IENVSFrame frame15 = envs1.nested(collection18.get(0), store1);
        envs1.push(frame15); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25) | author(13)
        
        IBagResult qRes114 = envs1.bind("realNumber");
        qres1.push(qRes114); // qres1|| bag(25)
        
        envs1.pop(); // envs1|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes115 = (IBagResult)qres1.pop(); // qres1||
        
        unionResCollection11.addAll(collection18);
        unionResCollection11.addAll(qRes115.getElements());
        
        unionRes11 = new BagResult(unionResCollection11);
        
        qres1.push(unionRes11); // qres1|| bag(13, 25)
        
        
        
        // QRES2 + ENVS2: ((emp.address) where number>20).(street, city)
        System.out.println("QRES2 + ENVS2: ((emp.address) where number>20).(street, city)");
        
        // AST2: ((emp.address) where number>20).(street, city)
        Expression expression2 = new Expression(
            new DotExpression(
                new WhereExpression(
                    new DotExpression(
                        new NameTerminal("emp"),
                        new NameTerminal("address")
                    ),
                    new GreaterThanExpression(
                        new NameTerminal("number"),
                        new IntegerTerminal(20)
                    )
                ),
                new CommaExpression(
                    new NameTerminal("street"),
                    new NameTerminal("city")
                )
            ));
        
        ENVS envs2 = new ENVS();           // envs2||
        QResStack qres2 = new QResStack(); // qres2||
        SBAStore store2 = new SBAStore();  // store2||
        
        store2.loadXML(".\\s9111_s10304_pr4\\res\\data.xml");
        envs2.init(store2.getEntryOID(), store2); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25)
        store2.PrintObjects(store2.retrieve(store2.getEntryOID()));
        System.out.println(store2.getString());
        

        // DotExpression
        IBagResult dotRes21 = new BagResult(null);
        ArrayList<ISingleResult> dotResCollection21 = new ArrayList<ISingleResult>();

        IBagResult qRes21 = envs2.bind("emp");
        qres2.push(qRes21); // qres2|| bag(2, 15)
        
        IBagResult qRes22 = (IBagResult)qres2.pop(); // qres2||
        
        // emp(2)
        ArrayList<ISingleResult> collection21 = (ArrayList<ISingleResult>)qRes22.getElements();
        IENVSFrame frame21 = envs2.nested(collection21.get(0), store2);
        envs2.push(frame21); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25) | number(3), fName(4), lName(5), address(6), married(11), book(12)
        
        IBagResult qRes23 = envs2.bind("address");
        qres2.push(qRes23); // qres2|| bag(6)

        envs2.pop(); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes24 = (IBagResult)qres2.pop(); // qres2||
        

        // emp(15)
        ArrayList<ISingleResult> collection22 = (ArrayList<ISingleResult>)qRes22.getElements();
        IENVSFrame frame22 = envs2.nested(collection21.get(1), store2);
        envs2.push(frame22); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25) | number(16), fName(17), lName(18), address(19), married(24)
        
        IBagResult qRes25 = envs2.bind("address");
        qres2.push(qRes25); // qres2|| bag(19)

        envs2.pop(); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes26 = (IBagResult)qres2.pop(); // qres2||
        
        dotResCollection21.addAll(qRes24.getElements());
        dotResCollection21.addAll(qRes26.getElements());
        dotRes21 = new BagResult(dotResCollection21);
        
        qres2.push(dotRes21); // qres2|| bag(6, 19)
        
        
        // WhereExpression
        IBagResult whereRes21 = new BagResult(null);
        ArrayList<ISingleResult> whereResCollection21 = new ArrayList<ISingleResult>();
        
        // address(6)
        IBagResult qRes27 = (IBagResult)qres2.pop(); // qres2||
        IENVSFrame frame23 = envs2.nested(((ArrayList<ISingleResult>)qRes27.getElements()).get(0), store2);
        envs2.push(frame23); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25) | street(7), number(8), zip(9), city(10)

        // GreaterThanExpression
        IBagResult qRes28 = envs2.bind("number");
        qres2.push(qRes28); // qres2|| bag(8)
        
        envs2.pop(); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes29 = (IBagResult)qres2.pop(); // qres2||

        ArrayList<ISingleResult> collection17 = (ArrayList<ISingleResult>)qRes29.getElements();
        ISBAObject sbaObj14 = store2.retrieve(((IReferenceResult)collection17.get(0)).getOIDValue());
        
        if (((IntegerObject)sbaObj14).getValue() > 20)
        	whereResCollection21.add(collection17.get(0));
        
        
        // address(19)
        IBagResult qRes30 = (IBagResult)qres2.pop(); // qres2||
        IENVSFrame frame24 = envs2.nested(((ArrayList<ISingleResult>)qRes27.getElements()).get(1), store2);
        envs2.push(frame24); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25) | street(20), number(21), zip(22), city(23)
        
        // GreaterThanExpression
        IBagResult qRes31 = envs2.bind("number");
        qres2.push(qRes31); // qres2|| bag(21)
        
        envs2.pop(); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes32 = (IBagResult)qres2.pop(); // qres2||
        
        ArrayList<ISingleResult> collection19 = (ArrayList<ISingleResult>)qRes32.getElements();
        ISBAObject sbaObj15 = store2.retrieve(((IReferenceResult)collection19.get(0)).getOIDValue());
        
        if (((IntegerObject)sbaObj15).getValue() > 20)
        	whereResCollection21.add(collection19.get(0));
        
        whereRes21 = new BagResult(whereResCollection21);
        qres2.push(whereRes21); // qres1|| bag(8, 21)       
        
        
        // DotExpression
        IBagResult dotRes22 = new BagResult(null);
        ArrayList<ISingleResult> dotResCollection22 = new ArrayList<ISingleResult>();
        
        IBagResult qRes33 = (IBagResult)qres2.pop(); // qres2||

        // number(8)
        ArrayList<ISingleResult> collection23 = (ArrayList<ISingleResult>)qRes33.getElements();
        
        IENVSFrame frame25 = envs2.nested(collection23.get(0), store2);
        envs2.push(frame25); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25) | street(7), number(8), zip(9), city(10)

        IBagResult qRes34 = envs2.bind("street");
        qres2.push(qRes34); // qres2|| bag(7)

        IBagResult qRes35 = (IBagResult)qres2.pop(); // qres2||

        IBagResult qRes36 = envs2.bind("city");
        qres2.push(qRes36); // qres2|| bag(10)

        envs2.pop(); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes37 = (IBagResult)qres2.pop(); // qres2||


        // number(21)
        ArrayList<ISingleResult> collection26 = (ArrayList<ISingleResult>)qRes24.getElements();
        
        IENVSFrame frame26 = envs2.nested(collection26.get(0), store2);
        envs2.push(frame26); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25) | street(20), number(21), zip(22), city(23)

        IBagResult qRes38 = envs2.bind("street");
        qres2.push(qRes38); // qres2|| bag(20)

        IBagResult qRes39 = (IBagResult)qres2.pop(); // qres2||

        IBagResult qRes40 = envs2.bind("city");
        qres2.push(qRes40); // qres2|| bag(23)

        envs2.pop(); // envs2|| integerNumber(1), emp(2), emp(15), realNumber(25)
        IBagResult qRes41 = (IBagResult)qres2.pop(); // qres2||


        dotResCollection22.addAll(qRes34.getElements());
        dotResCollection22.addAll(qRes36.getElements());
        dotResCollection22.addAll(qRes38.getElements());
        dotResCollection22.addAll(qRes40.getElements());

        dotRes22 = new BagResult(dotResCollection22);
        
        qres2.push(dotRes22); // qres2|| bag(7, 10, 20, 23)        
	}
}